import React, {
  useMemo,
  useState,
  useEffect,
  useRef,
  useImperativeHandle
} from 'react';
import { View, ScrollView, Text } from '@tarojs/components';
import { AtIcon } from 'taro-ui';
import './index.scss';
import {
  FlowListProps,
  FlowListComponentHandle,
  PageList,
  ItemT
} from '../../../types/components/flow-list';
import NoData from '../no-data';
import { Fragment } from 'react';
import { shallowEqual } from '../../utils';
/**
 * FlowList 列表展示组件
 */
const FlowList: React.ForwardRefRenderFunction<
  FlowListComponentHandle,
  FlowListProps
> = (
  {
    api,
    apiData,
    initData,
    scrollStyle,
    onScroll,
    onScrollClick,
    scrollY = true,
    onScrollToUpper,
    onRefresherPulling,
    onRefresherRestore,
    onRefresherRefreshFun,
    onFetchedData,
    renderItem,
    renderListHeaderComponent,
    renderListEmptyComponent,
    renderLoadingComponent,
    refresherBackground,
    noMoreDataStyle,
    isScrollToTop = false,
    hasPopData = false,
    contentClassName,
    popDataFunc,
    scrollTop,
    refresherEnabled = true,
  }: FlowListProps,
  ref
) => {
    const [data, setData] = useState<any[]>(() => {
      return initData ? initData : [];
    });
    const [refreshing, setRefreshing] = useState(false);
    const [noMoreData, setNoMoreData] = useState(false);
    const [hasLoadData, setHasLoadData] = useState(false);
    const [apiProps, setApiProps] = useState(apiData);
    const [scrollIntoView, setScrollIntoView] = useState('');
    const pageNo = useRef(1);
    const loading = useRef(false);
    useEffect(() => {
      if (isScrollToTop) {
        setScrollIntoView('scrollDivTop');
      } else {
        setScrollIntoView('');
      }
    }, [isScrollToTop]);
    const onScrollFun = e => {
      let top = e.detail.scrollTop;
      if (top < 30) {
        setScrollIntoView('');
      }
      onScroll && onScroll(e);
    };
    useImperativeHandle(ref, () => {
      return {
        refresh() {
          onRefresherRefresh();
        },
        getData() {
          return data;
        },
        setData(res) {
          setData(res);
        }
      };
    });
    useEffect(() => {
      fetchData(true);
    }, [apiProps]);
    useEffect(
      function () {
        if (!shallowEqual(apiData, apiProps)) {
          setApiProps(apiData);
        }
      },
      [apiData, apiProps]
    );
    const fetchData = async (refresh: boolean | void): Promise<void> => {
      if (pageNo.current > 1) {
        if (loading.current) return;
        loading.current = true;
      }
      if (refresh) {
        pageNo.current = 1;
      }
      let params = { pageNo: pageNo.current, pageSize: 20, ...apiData };
      try {
        let res = api && (await api(params));
        if (!res) {
          loading.current = false;
          setRefreshing(false);
          if (!refresh) {
            setNoMoreData(true);
          } else {
            setHasLoadData(true);
          }
        } else {
          res && afterFetchData(res);
          loading.current = false;
        }
      } catch (res) {
        loading.current = false;
        setRefreshing(false);
        setHasLoadData(true);
        if (!refresh) {
          setNoMoreData(true);
        }
      }
    };
    const afterFetchData = (res: PageList<ItemT>) => {
      let resEntities = res && res.entities;
      let fetchData =
        resEntities && onFetchedData
          ? onFetchedData(res.entities || [], res)
          : null;
      let entities = fetchData || resEntities || [];
      let extData: any[] = [];
      if (pageNo.current === 1) {
        extData = [...entities];
        setNoMoreData(false);
      } else {
        extData = [...data, ...entities];
      }
      //  后台返回的数据有可能会少于pageSize但还有下一页数据
      if (entities.length < 20) {
        setNoMoreData(true);
      } else {
        pageNo.current++;
      }
      setData(extData);
      setHasLoadData(true);
      if (hasPopData) {
        popDataFunc && popDataFunc(extData);
      }
      setRefreshing(false);
    };
    const handleLoadMore = () => {
      if (loading.current || noMoreData) {
        return;
      }
      fetchData(false);
    };
    const onRefresherRefresh = () => {
      onRefresherRefreshFun && onRefresherRefreshFun();
      setRefreshing(true);
      fetchData(true);
    };
    const renderLoadingComponentDefault = () => {
      return (
        <View className="loading-wrap">
          <AtIcon
            className="loading-icon"
            value="loading-3"
            size="32"
            color="#aaa"
          ></AtIcon>
          <Text className="loading-text">加载中…</Text>
        </View>
      );
    };
    const renderListFooterComponent = () => {
      if (!hasLoadData) {
        return renderLoadingComponent
          ? renderLoadingComponent()
          : renderLoadingComponentDefault();
      }
      if (!data.length) return null;
      return (
        <View className="no-more" style={noMoreDataStyle}>
          {noMoreData ? '没有更多了' : '内容加载中...'}
        </View>
      );
    };
    const renderRowItem = useMemo(() => {
      if (data.length > 0) {
        return data.map((item, index) => {
          return renderItem(item, index);
        });
      } else if (data.length == 0 && hasLoadData) {
        if (renderListEmptyComponent) {
          return renderListEmptyComponent();
        } else {
          return (
            <NoData
              className="message-noData"
              preset="no-data"
              content="暂无数据"
            />
          );
        }
      } else {
        return <Fragment></Fragment>;
      }
    }, [data, hasLoadData, renderListEmptyComponent]);
    const renderHeader = useMemo(() => {
      return renderListHeaderComponent && renderListHeaderComponent();
    }, [renderListHeaderComponent]);
    return (
      <View className="flow-list-wrap">
        <ScrollView
          className="scrollview"
          scrollWithAnimation
          style={scrollStyle}
          scrollY={scrollY}
          refresherEnabled={refresherEnabled}
          refresherTriggered={refreshing}
          refresherBackground={refresherBackground}
          onRefresherRefresh={onRefresherRefresh}
          scrollIntoView={scrollIntoView}
          scrollTop={scrollTop}
          onRefresherPulling={onRefresherPulling}
          onRefresherRestore={onRefresherRestore}
          onScrollToUpper={onScrollToUpper}
          lowerThreshold={200}
          onScroll={e => onScroll && onScrollFun(e)}
          onScrollToLower={handleLoadMore}
          onClick={e => onScrollClick && onScrollClick(e)}
        >
          <View id="scrollDivTop"></View>
          {renderHeader}
          <View className={`list-guest list-guest-common ${contentClassName}`}>
            {renderRowItem}
            {renderListFooterComponent()}
          </View>
        </ScrollView>
      </View>
    );
  };
export default React.forwardRef(FlowList);
